package com.spring.housing.util;

import org.springframework.util.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

/**
 *
 * 时间工具
 *
 * @author tuzy create 2019年2月11日下午3:33:10
 * @see 使用Java8时间类写
 */
public class DateUtils {
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * yyyyMMddHHmmss
     */
    public static final String DATETIME_PATTERN2 = "yyyyMMddHHmmss";
    /**
     * yyyy/MM/dd HH:mm:ss
     */
    public static final String DATETIME_PATTERN3 = "yyyy/MM/dd HH:mm:ss";
    /**
     * yyyyMMddHHmmssSSS
     */
    public static final String DATETIME_PATTERN4 = "yyyyMMddHHmmssSSS";

    /**
     * yyyy-MM-dd HH:mm:ss.SSS
     */
    public static final String DATETIME_PATTERN5 = "yyyy-MM-dd HH:mm:ss.SSS";

    /**
     * yyyy-MM-dd
     */
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * yyyyMMdd
     */
    public static final String DATE_PATTERN2 = "yyyyMMdd";
    /**
     * yyyy/MM/dd
     */
    public static final String DATE_PATTERN3 = "yyyy/MM/dd";

    /**
     * yyyyMM
     */
    public static final String DATE_PATTERN4 = "yyyyMM";

    /**
     * yyyy年MM月
     */
    public static final String DATE_PATTERN5 = "yyyy年MM月";

    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DATETIME_PATTERN);

    /**
     * yyyyMMddHHmmss
     */
    public static final DateTimeFormatter DATETIME_FORMATTER2 = DateTimeFormatter.ofPattern(DATETIME_PATTERN2);

    /**
     * yyyy/MM/dd HH:mm:ss
     */
    public static final DateTimeFormatter DATETIME_FORMATTER3 = DateTimeFormatter.ofPattern(DATETIME_PATTERN3);

    /**
     * yyyyMMddHHmmssSSS
     */
    public static final DateTimeFormatter DATETIME_FORMATTER4 = DateTimeFormatter.ofPattern(DATETIME_PATTERN4);

    /**
     * yyyy-MM-dd
     */
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN);

    /**
     * yyyyMMdd
     */
    public static final DateTimeFormatter DATE_FORMATTER2 = DateTimeFormatter.ofPattern(DATE_PATTERN2);

    /**
     * yyyy/MM/dd
     */
    public static final DateTimeFormatter DATE_FORMATTER3 = DateTimeFormatter.ofPattern(DATE_PATTERN3);

    public static final ZoneId ZONE = ZoneOffset.systemDefault();

    /**
     * 返回预设Format的当前日期字符串
     */
    public static String now() {
        return format(LocalDateTime.now());
    }

    /**
     * 格式化时间
     *
     * @param date
     * @return
     */
    public static String formatTime(Date date, String format) {
        return format(date, format);
    }

    /**
     * 使用预设Format格式化Date成字符串 yyyy-MM-dd HH:mm:ss
     */
    public static String format(Date date) {
        return format(LocalDateTime.ofInstant(date.toInstant(), ZONE));
    }

    public static String format(TemporalAccessor date) {
        return date == null ? null : DATETIME_FORMATTER.format(date);
    }



    /**
     * 使用参数Format格式化Date成字符串
     */
    public static String format(Date date, String pattern) {
        return format(toLocalDateTime(date), DateTimeFormatter.ofPattern(pattern));
    }

    public static String format(Date date, DateTimeFormatter pattern) {
        return format(toLocalDateTime(date), pattern);
    }

    public static String format(TemporalAccessor date, DateTimeFormatter pattern) {
        return pattern.format(date);
    }

    public static String format(DateTimeFormatter pattern) {
        return pattern.format(LocalDateTime.now());
    }

    public static LocalDateTime toLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZONE);
    }

    public static Date toDate(LocalDateTime date) {
        return Date.from(date.atZone(ZONE).toInstant());
    }

    public static Date toDate(LocalDate date) {
        return Date.from(date.atStartOfDay().atZone(ZONE).toInstant());
    }



    public static String formatObj(Object obj,String pattern){
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(obj);
    };

    /**
     * 计算时间小时差（秒钟） 返回两个时间的秒数
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int timeDifferenceForSecond(String startTime, String endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int min = 0;
        try {
            long from = sdf.parse(startTime).getTime();
            long to = sdf.parse(endTime).getTime();
            min = (int) ((to - from) / (1000));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return min;
    }

    /**
     * 计算时间小时差（秒钟） 返回两个时间的秒数 getTime
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int timeDifferenceForSecondGetTime(long from, long to) {
        int min = 0;
        min = (int) ((to - from) / (1000));
        return min;
    }

    /**
     * 计算时间天数差（秒钟） 返回两个时间的相隔天数
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int timeDifferenceForDayGetTime(long from, long to) {
        int min = 0;
        min = (int) ((to - from) / (1000) / (60) / (60) / (24));
        return min;
    }

    /**
     * 判断时间大小 whether 是否大于value  是返回true  否返回false
     * @param whether
     * @param value
     * @return
     */
    public static boolean ifDateSize(long whether, long value) {
        if(whether>=value) {
            return true;
        }else {
            return false;
        }
    }

    /**
     *
     * <pre>
     * 使用预设格式将字符串转为Date(支持如下格式的字符串时间转换，同时支持1970到现在的毫秒数的字符串转换
     * the milliseconds since January 1, 1970, 00:00:00 GMT)
     *   "yyyy-MM-dd HH:mm:ss"
     *   "yyyyMMddHHmmss"
     *   "yyyy/MM/dd HH:mm:ss"
     *   "yyyy-MM-dd"
     *   "yyyyMMdd"
     *   "yyyy/MM/dd"
     * </pre>
     */
    public static Date parse(String strDate) {
        if (StringUtils.hasText(strDate)) {
            LocalDateTime dateTime = null;
            int length = strDate.length();
            if (strDate.contains("/") && strDate.contains(":")) {
                dateTime = LocalDateTime.parse(strDate, DATETIME_FORMATTER3);
            } else if (strDate.contains("/")) {
                return toDate(LocalDate.parse(strDate, DATE_FORMATTER3));
            } else if (strDate.contains(":")) {
                dateTime = LocalDateTime.parse(strDate, DATETIME_FORMATTER);
            } else if (strDate.contains("-")) {
                return toDate(LocalDate.parse(strDate, DATE_FORMATTER));
            } else if (length == DATETIME_PATTERN2.length()) {
                dateTime = LocalDateTime.parse(strDate, DATETIME_FORMATTER2);
            } else if (length == DATE_PATTERN2.length()) {
                return toDate(LocalDate.parse(strDate, DATE_FORMATTER2));
            } else {
                throw new RuntimeException("unsupport parse dateString:" + strDate);
            }
            return toDate(dateTime);
        }
        return null;
    }

    /**
     * 使用参数Format将字符串转为Date
     */
    public static Date parse(String strDate, String pattern) {
        if (StringUtils.hasText(strDate)) {
            LocalDateTime dateTime = LocalDateTime.parse(strDate, DateTimeFormatter.ofPattern(pattern));
            return toDate(dateTime);
        }
        return null;
    }

    /**
     * 在日期上增加数个整月
     */
    public static Date plusMonths(Date date, long months) {
        return toDate(toLocalDateTime(date).plusMonths(months));
    }

    /**
     * 在日期上加多少天
     *
     * @param date
     * @param n
     * @return
     */
    public static Date plusDays(Date date, long days) {
        return toDate(toLocalDateTime(date).plusDays(days));
    }

    /**
     * 在日期上增加小时
     */
    public static Date addHour(Date date, long hours) {
        return toDate(toLocalDateTime(date).plusHours(hours));
    }

    /**
     * 在日期上增加数个整分钟
     */
    public static Date addMinute(Date date, long minute) {
        return toDate(toLocalDateTime(date).plusMinutes(minute));
    }

    /**
     * 在日期上增加数个整秒
     */
    public static Date addSecond(Date date, long seconds) {
        return toDate(toLocalDateTime(date).plusSeconds(seconds));
    }


    /**
     * 校验时间是否天数是在当前天数之后
     *
     * @param date
     */
    public static boolean checkTimeAfterCurrent(Date date) {
        return date.after(new Date());
    }

    public static float getUseSecond(Date date) {
        long before = date.getTime();
        long curr = new Date().getTime();
        float difference = curr - before;
        float second = difference / 1000;
        return second;
    }

    public static int getUseTime(Date date) {
        long before = date.getTime();
        long curr = new Date().getTime();
        long difference = curr - before;
        return (int) difference;
    }

    /**
     * 获取某天最早时间
     *
     * @param date
     * @return
     */
    public static Date dayFirst(Date date) {
        LocalDateTime today = toLocalDateTime(date);
        return toDate(LocalDateTime.of(today.getYear(), today.getMonth(), today.getDayOfMonth(), 0, 0, 0));
    }

    /**
     * 获取当天最早时间
     *
     * @return
     */
    public static Date dayFirst() {
        LocalDateTime today = LocalDateTime.now();
        return toDate(LocalDateTime.of(today.getYear(), today.getMonth(), today.getDayOfMonth(), 0, 0, 0));
    }

    /**
     * 获取昨天最早时间
     *
     * @return
     */
    public static Date yesterdayFirst() {
        LocalDateTime today = LocalDateTime.now();
        return toDate(LocalDateTime.of(today.getYear(), today.getMonth(), today.getDayOfMonth(), 0, 0, 0).minusDays(1));
    }

    /**
     * 获取昨天最晚时间
     *
     * @return
     */
    public static Date yesterdayEnd() {
        LocalDateTime today = LocalDateTime.now();
        return toDate(LocalDateTime.of(today.getYear(), today.getMonth(), today.getDayOfMonth(), 23, 59, 59).minusDays(1));
    }


    /**
     * 获取月第一天
     *
     * @param date
     */
    public static Date monthFirstDay(Date date) {
        LocalDateTime today = toLocalDateTime(date);
        return toDate(LocalDateTime.of(today.getYear(), today.getMonth(), 1, 0, 0, 0));
    }

    /**
     * 获取月最后一天
     *
     * @param date
     */
    public static Date monthEndDay(Date date) {
        LocalDateTime time = toLocalDateTime(date).with(TemporalAdjusters.lastDayOfMonth());
        time = time.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
        return toDate(time);
    }


    /**
     * 获取当月第一天
     * @return
     */
    public static Date getMonthFirst() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DATE, 1);// 设置为1号,当前日期既为本月第一天
        return cal.getTime();
    }

    /**
     * 获取当月最后一天
     * @return
     */
    public static Date getMonthLast() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DATE, 1);// 设置为1号,当前日期既为本月第一天
        cal.roll(Calendar.DATE, -1);// 日期回滚一天,即月末
        return cal.getTime();
    }

    /**
     * 相差多少月的第一天
     * @param month
     * @return
     */
    public static Date getMonthFirst(int month) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, month);// 设置为1号,当前日期既为本月第一天
        cal.set(Calendar.DATE, 1);// 设置为1号,当前日期既为本月第一天
        return cal.getTime();
    }



    public static float getBetweenMinute(Date start, Date end) {
        if (start == null || end == null) {
            return 0;
        }
        long l_start = start.getTime();
        long l_end = end.getTime();
        float difference = Math.abs(l_end - l_start);
        float minute = difference / 1000 / 60;
        return minute;
    }

    public static String getHourMinute(long distance) {
        long hour = distance / (3600 * 1000);
        long minute = (distance - hour * 3600 * 1000) / (60 * 1000);
        return hour + "小时" + minute + "分钟";
    }


    public static boolean isWeek(Date date) {
        LocalDateTime dt = toLocalDateTime(date);
        if (dt.getDayOfWeek().equals(DayOfWeek.SATURDAY) || dt.getDayOfWeek().equals(DayOfWeek.SUNDAY)) {
            return true;
        } else {
            return false;
        }
    }


    public static int calLastedTime(Date startDate,int beginSecond) {
        long a = new Date().getTime();
        long b = startDate.getTime();
        int c = (int)((a - b) / 1000);
        c = (beginSecond-c);
        return c;
    }



    public static void main(String[] args) {
        // System.out.println("2017-10-29 12:12:12 ==》"
        // + format(parse("2017-10-29 12:12:12"), "yyyyMMddHHmmss"));
        // System.out.println("2017-10-29 12:12:12 ==》" + format(parse("2017-10-29 12:12:12")));
        // System.out.println("2017-10-29 ==》" + format(parse("2017-10-29")));
        // System.out.println("20171029121212 ==》" + format(parse("20171029121212")));
        // System.out.println("20171029 ==》" + format(parse("20171029")));
        // System.out.println(String.valueOf(new Date().getTime()) + " ==》"
        // + format(parse(String.valueOf(new Date().getTime()))));
        // System.out.println("monthFirstDay ==》" + format(monthFirstDay(new Date())));
        // System.out.println("monthEndDay ==》" + format(monthEndDay(new Date())));
        // System.out.println("2017-10-29 12:12:12 ==》" + isWeek(parse("2017-10-29 00:00:00")));
        // System.out.println("20171029 ==》" + format(dayFirst(new Date())));
        // System.out.println(format(new Date(),DATE_PATTERN2));
        // System.out.println(Sign.MD5("00000"+format(new Date(),DATE_PATTERN2)));

        // System.out.println(parse("2019-04-26 11:42:36.0", "yyyy-MM-dd HH:mm:ss.0"));
        long endTime = parse("2020-08-16 03:59:59", "yyyy-MM-dd HH:mm:ss").getTime();



        System.out.println(plusMonths(parse("2021-11-26 23:59:59", "yyyy-MM-dd HH:mm:ss"),3));
        // long endTime = parse("2021-06-20 23:59:59", "yyyy-MM-dd HH:mm:ss").getTime();
        System.out.println(timeDifferenceForDayGetTime(new Date().getTime(), endTime));
    }
}
